package com.filemanager;

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

class FileTreePanel extends JPanel {

    private File clipboardFile = null;  // 复制/剪切的文件或文件夹
    private boolean isCutOperation = false;

    private JTree tree;

    public FileTreePanel() {
        // 初始化根节点，使用当前工作目录
        File rootFile = new File("D:\\database smu");
        DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(rootFile.getName());
        createChildren(rootFile, rootNode);

        tree = new JTree(rootNode);

        // 右键弹出菜单
        tree.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e)) {
                    int row = tree.getClosestRowForLocation(e.getX(), e.getY());
                    tree.setSelectionRow(row);
                    showContextMenu(e.getX(), e.getY());
                }
            }
        });

        JScrollPane scrollPane = new JScrollPane(tree);
        this.setLayout(new BorderLayout());
        this.add(scrollPane, BorderLayout.CENTER);
    }

    // 递归加载文件夹和文件
    private void createChildren(File fileRoot, DefaultMutableTreeNode node) {
        File[] files = fileRoot.listFiles();
        if (files == null) return;

        for (File file : files) {
            DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(file.getName());
            node.add(childNode);
            if (file.isDirectory()) {
                createChildren(file, childNode);
            }
        }
    }

    // 右键菜单展示
    private void showContextMenu(int x, int y) {
        JPopupMenu popupMenu = new JPopupMenu();

        JMenuItem newItem = new JMenuItem("新建文件夹");
        JMenuItem renameItem = new JMenuItem("重命名");
        JMenuItem deleteItem = new JMenuItem("删除");
        JMenuItem copyItem = new JMenuItem("复制");
        JMenuItem cutItem = new JMenuItem("剪切");
        JMenuItem pasteItem = new JMenuItem("粘贴");

        newItem.addActionListener(e -> createNewFolder());
        renameItem.addActionListener(e -> renameNode());
        deleteItem.addActionListener(e -> deleteNode());
        copyItem.addActionListener(e -> copyFile(false));
        cutItem.addActionListener(e -> copyFile(true));
        pasteItem.addActionListener(e -> pasteFile());

        popupMenu.add(newItem);
        popupMenu.add(renameItem);
        popupMenu.add(deleteItem);
        popupMenu.addSeparator();
        popupMenu.add(copyItem);
        popupMenu.add(cutItem);
        popupMenu.add(pasteItem);

        popupMenu.show(tree, x, y);
    }

    // 复制/剪切文件或文件夹
    private void copyFile(boolean isCut) {
        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selectedNode == null) return;

        File selectedFile = getFileFromNode(selectedNode);
        clipboardFile = selectedFile;
        isCutOperation = isCut;

        String type = isCut ? "剪切" : "复制";
        JOptionPane.showMessageDialog(this, type + "了: " + selectedFile.getName());
    }

    // 粘贴文件或文件夹到目标目录
    private void pasteFile() {
        if (clipboardFile == null) return;

        DefaultMutableTreeNode targetNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (targetNode == null) return;

        File targetDir = getFileFromNode(targetNode);
        if (!targetDir.isDirectory()) {
            JOptionPane.showMessageDialog(this, "请选择一个文件夹进行粘贴");
            return;
        }

        File destFile = new File(targetDir, clipboardFile.getName());

        try {
            if (clipboardFile.isDirectory()) {
                copyDirectory(clipboardFile, destFile);
            } else {
                Files.copy(clipboardFile.toPath(), destFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }

            if (isCutOperation) {
                deleteRecursively(clipboardFile);
                isCutOperation = false;
            }

            // 更新树模型，新增节点
            targetNode.add(new DefaultMutableTreeNode(destFile.getName()));
            ((DefaultTreeModel) tree.getModel()).reload(targetNode);

            clipboardFile = null;

            JOptionPane.showMessageDialog(this, "粘贴成功！");

        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "粘贴失败: " + ex.getMessage());
        }
    }

    // 递归复制目录
    private void copyDirectory(File source, File target) throws Exception {
        if (!target.exists()) {
            target.mkdirs();
        }
        for (File file : source.listFiles()) {
            File dest = new File(target, file.getName());
            if (file.isDirectory()) {
                copyDirectory(file, dest);
            } else {
                Files.copy(file.toPath(), dest.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
        }
    }

    // 递归删除目录或文件
    private void deleteRecursively(File file) {
        if (file.isDirectory()) {
            for (File child : file.listFiles()) {
                deleteRecursively(child);
            }
        }
        file.delete();
    }

    // 根据树节点路径返回对应的 File 对象
    private File getFileFromNode(DefaultMutableTreeNode node) {
        TreeNode[] path = node.getPath();
        StringBuilder fullPath = new StringBuilder(System.getProperty("user.dir"));
        // 跳过根节点名
        for (int i = 1; i < path.length; i++) {
            fullPath.append(File.separator).append(path[i].toString());
        }
        return new File(fullPath.toString());
    }

    // 新建文件夹
    private void createNewFolder() {
        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selectedNode == null) return;

        String folderName = JOptionPane.showInputDialog(this, "输入新文件夹名称：");
        if (folderName == null || folderName.trim().isEmpty()) return;

        File parentDir = getFileFromNode(selectedNode);
        if (!parentDir.isDirectory()) {
            JOptionPane.showMessageDialog(this, "请选择一个文件夹作为父目录");
            return;
        }

        File newFolder = new File(parentDir, folderName);
        if (newFolder.mkdir()) {
            selectedNode.add(new DefaultMutableTreeNode(folderName));
            ((DefaultTreeModel) tree.getModel()).reload(selectedNode);
            JOptionPane.showMessageDialog(this, "新建文件夹成功");
        } else {
            JOptionPane.showMessageDialog(this, "新建文件夹失败");
        }
    }

    // 重命名文件或文件夹
    private void renameNode() {
        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selectedNode == null || selectedNode.isRoot()) return;

        File oldFile = getFileFromNode(selectedNode);
        String newName = JOptionPane.showInputDialog(this, "输入新名称：", selectedNode.getUserObject());
        if (newName == null || newName.trim().isEmpty()) return;

        File newFile = new File(oldFile.getParent(), newName);
        if (oldFile.renameTo(newFile)) {
            selectedNode.setUserObject(newName);
            ((DefaultTreeModel) tree.getModel()).reload((TreeNode) selectedNode.getParent());
            JOptionPane.showMessageDialog(this, "重命名成功");
        } else {
            JOptionPane.showMessageDialog(this, "重命名失败");
        }
    }

    // 删除文件或文件夹
    private void deleteNode() {
        DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
        if (selectedNode == null || selectedNode.isRoot()) return;

        int confirm = JOptionPane.showConfirmDialog(this, "确认删除吗？", "提示", JOptionPane.YES_NO_OPTION);
        if (confirm != JOptionPane.YES_OPTION) return;

        File file = getFileFromNode(selectedNode);
        boolean success = deleteFileOrDirectory(file);

        if (success) {
            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) selectedNode.getParent();
            parent.remove(selectedNode);
            ((DefaultTreeModel) tree.getModel()).reload(parent);
            JOptionPane.showMessageDialog(this, "删除成功");
        } else {
            JOptionPane.showMessageDialog(this, "删除失败");
        }
    }

    // 递归删除，返回是否成功
    private boolean deleteFileOrDirectory(File file) {
        if (file.isDirectory()) {
            File[] contents = file.listFiles();
            if (contents != null) {
                for (File f : contents) {
                    if (!deleteFileOrDirectory(f)) return false;
                }
            }
        }
        return file.delete();
    }

    public JTree getTree() {
        return tree;
    }
}
